package org.company.venus.dao.hibernate;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

@Repository
public class BaseDao<T> extends HibernateDaoSupport {
    
    @Autowired
    public void setSuperSessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }
    
    public Serializable save(T t) {
        return this.getHibernateTemplate().save(t);
    }
    
    /**
     * not founder,return null
     * @param id
     * @param clazz
     * @return
     */
    public T get(Class<T> clazz,Serializable id) {
        return this.getHibernateTemplate().get(clazz,id);
    }
    
    /**
     * not founder,throw exception
     * @param id
     * @param clazz
     * @return
     */
    public T load(Class<T> clazz,Serializable id) {
        return this.getHibernateTemplate().load(clazz, id);
    }
    
    public void update(T t) {
        this.getHibernateTemplate().update(t);
    }
    
    public void saveOrUpdate(T t){
        this.getHibernateTemplate().saveOrUpdate(t);
    }
    
    public void delete(T t) {
        this.getHibernateTemplate().delete(t);
    }
    
    /**
     * 批量插入/更新
     * @param list
     */
    public void batchInsertOrUpdate(final List<T> list) {
        this.getHibernateTemplate().saveOrUpdateAll(list);
    }
    
    /**
     * 分页查询
     * @param hql
     * @param params
     * @param offset
     * @param pageSize
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<T> pageQuery(final String hql,final List<Object> params,final int offset,final int pageSize) {
        return this.getHibernateTemplate().executeFind(new HibernateCallback<List<T>>() {
            @Override
            public List<T> doInHibernate(Session session) throws HibernateException,
                    SQLException {
                Query query = session.createQuery(hql);
                for(int i=0 ; i < params.size() ; i++) {
                    query.setParameter(i, params.get(i));
                }
                return query.setFirstResult(offset).setMaxResults(pageSize).list();
            }
        });
    }
    
    /**
     * 
     * @param clazz
     * @param orderByProperty,orderBy语句
     * @param firstResult
     * @param maxResults
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<T> pageQuery(final Class<T> clazz,final String orderByProperty,
            final int firstResult,final int maxResults) {
        return this.getHibernateTemplate().executeFind(new HibernateCallback<List<T>>() {
            @Override
            public List<T> doInHibernate(Session session)
                    throws HibernateException, SQLException {
                Criteria criteria = session.createCriteria(clazz)
                        .setFirstResult(firstResult)
                        .setMaxResults(maxResults)
                        .addOrder(Order.desc(orderByProperty));
                return criteria.list();
            }
        });
    }
    
    public List<T> pageQuery(final String hql,final int offset,final int pageSize) {
        List<Object> params = new ArrayList<Object>();
        return this.pageQuery(hql, params, offset, pageSize);
    }
    
    
    @SuppressWarnings("unchecked")
    public List<T> queryAll(String hqlStr) {
        return this.getHibernateTemplate().find(hqlStr);
    }
    
    @SuppressWarnings("unchecked")
    public List<T> query(String hqlStr,Object...objects){
        return this.getHibernateTemplate().find(hqlStr, objects);
    }
    
    @SuppressWarnings("unchecked")
    public List<T> queryByNamed(String queryName) {
        return this.getHibernateTemplate().findByNamedQuery(queryName);
    }
}
